/** @file   system.c
    @author M. P. Hayes, UCECE
    @date   21 August 2007
    @brief  Temperature control system. 
*/
#include "heater.h"	/** @see heater */
#include "temp_sensor.h" 
#include "control.h"	/** @see control */


/* The temperature sensor has a conversion time of 0.75 s
   so no point having a period shorter than 1 s.  */
enum {SYSTEM_POLL_PERIOD = 1};


static uint16_t system_ticks;
static uint16_t system_period;
static uint8_t  temp_current;
static bool temp_ok;


/** Attempt to maintain current temperature at setpoint.
    @param temp_setpoint desired setpoint temperature
    @param ptemp_current pointer to current temperature
    @return 1 if have new current temp, 0 if no change, negative for error  */
int8_t system_update (uint8_t temp_setpoint, uint8_t *ptemp_current)
{
    int8_t ret = 0;

    heater_update ();

    /* The temperature reading and control update are not performed in
       the same tick; this helps to reduce display refresh jitter.  */
    switch (system_ticks++)
    {
    case 0:
	ret = temp_sensor_get (0, &temp_current);
	temp_ok = ret > 0;
	if (! temp_ok)
	{
	    /* If have read error turn off heater for safety.  */
	    heater_set (0);
	}
	break;

    case 1:
	if (temp_ok)
	{
	    int8_t heater_percent;
	    
	    heater_percent = control_update (temp_setpoint - temp_current);
	    
	    heater_set (heater_percent);

	    /* Return current temperature.  */
	    *ptemp_current = temp_current;
	    ret = 1;
	}
	break;

    default:
	if (system_ticks >= system_period)
	    system_ticks = 0;
	break;
    }
	
    return ret;
}


/** Initialise system.
    @param update_rate the rate \c system_update is called  */
void system_init (uint16_t update_rate)
{
    heater_init (update_rate);
    heater_set (0);

    control_init (1.0 / SYSTEM_POLL_PERIOD);

    temp_sensor_init ();
    temp_sensor_start (0);

    system_ticks = 0;
    system_period = update_rate * SYSTEM_POLL_PERIOD;

    temp_current = 0;
}
